package com.yingjia.yingjiauniversity.utils;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Process;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * AppUtils
 * <ul>
 * <li>{@link AppUtil#isNamedProcess(Context, String)}</li>
 * </ul>
 *
 * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2014-5-07
 */
public class AppUtil {

    private static Logger logger = LoggerFactory.getLogger(AppUtil.class);

    private AppUtil() {
        throw new AssertionError();
    }

    private static PropertyChangeListener _listener;

    /**
     * Sets quit callback.
     *
     * @param listener the listener
     */
    public static void setQuitCallback(PropertyChangeListener listener) {
        _listener = listener;
    }

    private static void stopAllServices(Context context) {
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> serviceInfos = manager.getRunningServices(Integer.MAX_VALUE);
        final int NS = serviceInfos != null ? serviceInfos.size() : 0;
        for (int i = 0; i < NS; i++) {
            ActivityManager.RunningServiceInfo si = serviceInfos.get(i);
            if (!si.started || si.pid != Process.myPid()) {
                continue;
            }
            Intent intent = new Intent();
            intent.setComponent(si.service);
            context.stopService(intent);
        }
    }

    /**
     * 程序退出
     */
    public static void appQuit(Context context, Stack<Activity> activityStack) {
        while (!activityStack.isEmpty()) {
            activityStack.pop().finish();
        }
        stopAllServices(context);
        //触发应用关闭通知
        if (_listener != null) {
            _listener.propertyChange(null);
        }
        Process.killProcess(Process.myPid());
    }

    /**
     * whether this process is named with processName
     *
     * @param context
     * @param processName
     * @return <ul>
     * return whether this process is named with processName
     * <li>if context is null, return false</li>
     * <li>if {@link ActivityManager#getRunningAppProcesses()} is null, return false</li>
     * <li>if one process of {@link ActivityManager#getRunningAppProcesses()} is equal to processName, return
     * true, otherwise return false</li>
     * </ul>
     */
    public static boolean isNamedProcess(Context context, String processName) {
        if (context == null) {
            return false;
        }

        int pid = Process.myPid();
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> processInfoList = manager.getRunningAppProcesses();
        if (processInfoList == null || processInfoList.isEmpty()) {
            return false;
        }

        for (RunningAppProcessInfo processInfo : processInfoList) {
            if (processInfo != null && processInfo.pid == pid
                    && processName.equalsIgnoreCase(processInfo.processName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * whether application is in background
     * <ul>
     * <li>need use permission android.permission.GET_TASKS in Manifest.xml</li>
     * </ul>
     *
     * @param context
     * @return if application is in background return true, otherwise return false
     */
    public static boolean isApplicationInBackground(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> taskList = am.getRunningTasks(1);
        if (taskList != null && !taskList.isEmpty()) {
            ComponentName topActivity = taskList.get(0).topActivity;
            if (topActivity != null && !topActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否存在launcher
     *
     * @param context
     * @return
     */
    public static boolean hasLauncherDefined(Context context) {
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
        boolean rt = intent != null;
        return rt;
    }


    /**
     * 收集设备参数信息
     *
     * @param ctx
     */
    public static Map<String, String> collectDeviceInfo(Context ctx) {
        Map<String, String> deviceInfo = new HashMap<String, String>();
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);

            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                deviceInfo.put("versionName", versionName);
                deviceInfo.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            logger.error("an error occured when collect package info", e);
        }

        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                deviceInfo.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                logger.error("an error occured when collect crash info", e);
            }
        }

        return deviceInfo;
    }


    /**
     * 获取应用版本
     *
     * @param context the context
     * @return the version info
     */
    public static String getVersionInfo(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
            return info.versionName;
        } catch (Exception e) {
            logger.warn("getVersionInfo throw exception on : {}", e.getMessage());
            return "版本号未知...";
        }
    }

    /**
     * Gets version code.
     *
     * @param context the context
     * @return the version code
     */
    public static int getVersionCode(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
            return info.versionCode;
        } catch (Exception e) {
            logger.warn("getVersionCode throw exception on : {}", e.getMessage());
            return 0;
        }
    }

    /**
     * Gets package name.
     *
     * @param context the context
     * @return the package name
     */
    public static String getPackageName(Context context) {
        return context.getApplicationContext().getPackageName();
    }

    /**
     * 根据包名判断应用是否已经安装。
     *
     * @param context     上下文
     * @param packageName 包名
     * @return 如果应用已经安装，则返回true，否则返回false.
     */
    public static boolean isAppExist(Context context, String packageName) {
        PackageManager pm = context.getPackageManager();
        List<PackageInfo> infoList = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
        for (PackageInfo info : infoList) {
            if (packageName.equals(info.packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * <是否为主进程>
     *
     * @param context the context
     * @return the boolean
     * @author: guoxiangxun
     * @date: Sep 20, 2017 11:22:30 AM
     * @version: v1.0
     */
    public static boolean isAppProcess(Context context) {
        String packageName = context.getPackageName();
        int pid = Process.myPid();
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> infoList = am.getRunningAppProcesses();
        for (RunningAppProcessInfo info : infoList) {
            if (info.pid == pid && packageName.equals(info.processName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * get the launcher activity class full name of an application by the package name
     *
     * @param context     the context of current application
     * @param packageName the package name of the application (it can be any application)
     * @return
     */
    public static String getLauncherActivityNameByPackageName(Context context, String packageName) {
        String className = null;
        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);//android.intent.action.MAIN
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);//android.intent.category.LAUNCHER
        resolveIntent.setPackage(packageName);
        List<ResolveInfo> resolveinfoList = context.getPackageManager().queryIntentActivities(resolveIntent, 0);
        ResolveInfo resolveinfo = resolveinfoList.iterator().next();
        if (resolveinfo != null) {
            className = resolveinfo.activityInfo.name;
        }
        return className;
    }
}
